﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using Kay.Communication.Framework.Common;
using Kay.Communication.Framework.Custom_Errors;
using Kay.Communication.Framework.Custom_EventArgs;

namespace Kay.Communication.Framework
{
    /// <summary>
    /// 基础通信类
    /// </summary>
    public class BaseCommunication : IDisposable
    {
        /// <summary>
        /// 通信对象对象
        /// </summary>
        private Socket _socket;

        /// <summary>
        /// 当前对象使用的资源是否已经释放
        /// </summary>
        private bool _disposed;

        /// <summary>
        /// 基础通信对象模型
        /// </summary>
        private CommunicationModes _communicationMode = CommunicationModes.Unknown;

        /// <summary>
        /// 当调用方法返回 False 时，可以查看原因
        /// </summary>
        public string ErrorInfo { get; private set; }

        /// <summary>
        /// 当调用方法返回 False 时，对应的错误码
        /// </summary>
        public CommunicationErrors ErrorCode { get; private set; }

        /// <summary>
        /// 当前通信对象的初始化参数
        /// </summary>
        public CommunicationArgs CommunicationArgs { get; private set; }

        /// <summary>
        /// 联系人列表
        /// </summary>
        public List<ContactsInfo> Contacts { get; private set; }

        /// <summary>
        /// 获取当前通信对象的模型
        /// </summary>
        public CommunicationModes CommunicationMode
        {
            get { return _communicationMode; }
        }

        /// <summary>
        /// 获取或设置当前通信对象是否正在运行
        /// </summary>
        public bool IsRuning { get; private set; }

        /// <summary>
        /// 析构当前对象
        /// </summary>
        ~BaseCommunication()
        {
            Dispose(false);
        }

        /// <summary>
        /// 初始化基础通信对象
        /// </summary>
        public bool InitializeBaseCommunication(CommunicationArgs args)
        {
            if (_communicationMode != CommunicationModes.Unknown)
            {
                ErrorInfo = "当前通信对象已有模型。";
                ErrorCode = CommunicationErrors.HasMode;
                return false;
            }

            if (args.CommunicationMode == CommunicationModes.Unknown)
            {
                ErrorInfo = "通信对象的模型不能指定为未知。";
                ErrorCode = CommunicationErrors.Unknown;
                return false;
            }

            IsRuning = false;
            if (IsRuningChanged != null)
            {
                IsRuningChanged.Invoke(IsRuning);
            }

            _communicationMode = args.CommunicationMode;
            CommunicationArgs = args;
            if (Contacts == null)
                Contacts = new List<ContactsInfo>();
            _disposed = false;

            try
            {
                _socket = new Socket(args.AddressFamily, args.SocketType, args.ProtocolType)
                {
                    ReceiveBufferSize = args.MessageLength, // k * M * G
                    SendBufferSize = args.MessageLength // k * M * G
                };
                return true;
            }
            catch (SocketException e)
            {
                ErrorInfo = e.Message;
                ErrorCode = CommunicationErrors.CommunicationError;
                return false;
            }
        }

        /// <summary>
        /// 启动监听器监听本地客户端接入
        /// </summary>
        /// <returns></returns>
        public bool Listening()
        {
            if (_communicationMode == CommunicationModes.TcpServer && !_socket.IsBound)
            {
                _socket.Bind(CommunicationArgs.EndPoint);
                _socket.Listen(CommunicationArgs.Waiting);
                ThreadPool.QueueUserWorkItem(Listener, _socket);
                IsRuning = true;
                if (IsRuningChanged != null)
                {
                    IsRuningChanged.Invoke(IsRuning);
                }
                return true;
            }

            ErrorInfo = "当前通信对象不支持侦听操作。";
            ErrorCode = CommunicationErrors.ModeMismatching;
            return false;
        }

        /// <summary>
        /// 监听器
        /// </summary>
        /// <param name="obj"></param>
        private void Listener(object obj)
        {
            var socketServer = (Socket)obj;
            while (true)
            {
                if (!_socket.IsBound)
                {
                    break;
                }
                try
                {
                    var socketClient = socketServer.Accept();

                    var userInfo = new ContactsInfo
                    {
                        LoginTime = DateTime.Now,
                        Socket = socketClient,
                        RemoteEndPointByServer = socketClient.RemoteEndPoint.ToString(),
                        LocalEndPointByServer = socketClient.LocalEndPoint.ToString()
                    };
                    Contacts.Add(userInfo);
                    ThreadPool.QueueUserWorkItem(ServerReceive, socketClient);
                }
                catch (SocketException e)
                {
                    if (e.ErrorCode == 10004 && e.SocketErrorCode == SocketError.Interrupted)
                    {
                        break;
                    }
                    throw;
                }
            }
            socketServer.Close();
            IsRuning = false;
            if (IsRuningChanged != null)
            {
                IsRuningChanged.Invoke(IsRuning);
            }
        }

        /// <summary>
        /// 服务端收到消息处理
        /// </summary>
        /// <param name="obj">客户端对象</param>
        private void ServerReceive(object obj)
        {
            // 当前的 Socket 客户端
            var socketClient = (Socket)obj;
            while (true)
            {
                GC.Collect();
                try
                {
                    // 等待客户端发送消息，没有则阻止，没有超时
                    socketClient.Receive(new byte[0], 0, 0, SocketFlags.None);
                }
                catch (SocketException e)
                {
                    // 表示客户端断开连接，否则抛出异常
                    if (e.ErrorCode != 10054 || e.SocketErrorCode != SocketError.ConnectionReset)
                    {
                        // 表示有系统终止客户端连接，否则抛出异常
                        if (e.ErrorCode != 10053 || e.SocketErrorCode != SocketError.ConnectionAborted)
                        {
                            throw;
                        }
                    }
                    // 设置 Socket 离线
                    socketClient.Close();
                    SocketOffline(socketClient);
                    GC.Collect();
                    break;
                }
                catch (ObjectDisposedException)
                {
                    // Socket 已经释放
                    socketClient.Close();
                    SocketOffline(socketClient);
                    GC.Collect();
                    break;
                }

                // 获取与当前 Socket 关联的联系人信息
                var currentSocketClientContactsInfo = Contacts.Find(u => u.Socket == socketClient);

                // 如果找不到当前 Socket 对应的用户信息操作
                if (currentSocketClientContactsInfo == null)
                {
                    // 断开当前 Socket
                    socketClient.Close();
                    // 设置 Socket 离线
                    SocketOffline(socketClient);
                    GC.Collect();
                    break;
                }

                if (currentSocketClientContactsInfo.WebSocket)
                {
                    // 如果为 WebSocket 客户端则按此处理

                    // 帧的缓冲区，用于判断是否还有消息和是否关闭操作
                    var bytesFrame = new byte[1];
                    // 掩码标识缓冲区，判断是否使用掩码和确定数据长度
                    var bytesMaskFlag = new byte[1];
                    // 掩码缓冲区
                    var bytesMasks = new byte[4];
                    // 需要移除的缓冲区
                    var bytesRemove = new byte[8];
                    // 储存实际数据
                    var bytesReceived = new List<byte>();
                    while (true)
                    {
                        var lengthReceived = socketClient.Receive(bytesFrame, 0, 1, SocketFlags.None);
                        if (lengthReceived == 0)
                        {
                            // 如果读取不到消息则进行关闭操作
                            socketClient.Close();
                            SocketOffline(socketClient);
                            GC.Collect();
                            break;
                        }
                        // True 代表客户端调用了 Close 方法
                        var opcode = (bytesFrame[0] & 15) == 8;
                        if (opcode)
                        {
                            //var bytes = new byte[socketClient.Available + 1];
                            //socketClient.Receive(bytes, 1, bytes.Length - 1, SocketFlags.None);
                            //bytes[0] = bytesFrame[0];
                            //socketClient.Send(bytes);

                            // 进行关闭操作
                            socketClient.Close();
                            SocketOffline(socketClient);
                            GC.Collect();
                            break;
                        }

                        if (socketClient.Available < 1)
                        {
                            // 读完帧如果没有数据则进行关闭操作
                            socketClient.Close();
                            SocketOffline(socketClient);
                            GC.Collect();
                            break;
                        }

                        // 读取掩码标识
                        socketClient.Receive(bytesMaskFlag, 0, 1, SocketFlags.None);

                        // 计算数据长度
                        var payLoadLen = bytesMaskFlag[0] & 0x7F;
                        // 实际数据缓冲区
                        byte[] bytesLoadData;
                        if (payLoadLen == 126)
                        {
                            // 特殊长度 126 处理

                            // 读取不需要的信息
                            socketClient.Receive(bytesRemove, 0, 2, SocketFlags.None);
                            // 读取掩码
                            socketClient.Receive(bytesMasks, 0, 4, SocketFlags.None);
                            // 计算实际数据长度
                            payLoadLen = (ushort)(bytesRemove[0] << 8 | bytesRemove[1]);
                            // 初始化实际数据缓冲区
                            bytesLoadData = new byte[payLoadLen];
                            // 读取实际数据
                            socketClient.Receive(bytesLoadData, 0, payLoadLen, SocketFlags.None);
                        }
                        else if (payLoadLen == 127)
                        {
                            // 特殊长度 127 处理

                            socketClient.Receive(bytesRemove, 0, 8, SocketFlags.None);
                            socketClient.Receive(bytesMasks, 0, 4, SocketFlags.None);
                            var bytesUlong = new byte[8];
                            for (var i = 0; i < 8; i++)
                            {
                                bytesUlong[i] = bytesRemove[7 - i];
                            }
                            payLoadLen = (int)BitConverter.ToUInt64(bytesUlong, 0);
                            bytesLoadData = new byte[payLoadLen];
                            socketClient.Receive(bytesLoadData, 0, payLoadLen, SocketFlags.None);
                        }
                        else
                        {
                            // 其他长度数据处理

                            socketClient.Receive(bytesMasks, 0, 4, SocketFlags.None);
                            bytesLoadData = new byte[payLoadLen];
                            try
                            {
                                socketClient.Receive(bytesLoadData, 0, payLoadLen, SocketFlags.None);
                            }
                            catch (SocketException e)
                            {
                                // 表示客户端断开连接，否则抛出异常
                                if (e.ErrorCode != 10054 || e.SocketErrorCode != SocketError.ConnectionReset)
                                {
                                    // 表示有系统终止客户端连接
                                    if (e.ErrorCode != 10053 || e.SocketErrorCode != SocketError.ConnectionAborted)
                                    {
                                        throw;
                                    }
                                }
                                // 设置 Socket 离线
                                SocketOffline(socketClient);
                                GC.Collect();
                                break;
                            }
                        }

                        // 是否包含掩码
                        var maskFlag = (bytesMaskFlag[0] & 0x80) == 0x80;
                        // 处理掩码数据
                        if (maskFlag)
                        {
                            for (var i = 0; i < payLoadLen; i++)
                            {
                                bytesLoadData[i] = (byte)(bytesLoadData[i] ^ bytesMasks[i % 4]);
                            }
                        }

                        // 将数据加入存储区
                        bytesReceived.AddRange(bytesLoadData);

                        // 是否还有数据
                        var fin = (bytesFrame[0] & 0x80) == 0x80;
                        if (fin)
                        {
                            break;
                        }
                    }
                    if (bytesReceived.Count <= 128)
                    {
                        var text = CommunicationArgs.Encoding.GetString(bytesReceived.ToArray());
                        if (text == "1")
                        {
                            var path = AppDomain.CurrentDomain.BaseDirectory;

                        }
                        continue;
                    }

                    // 处理正常的一次消息
                    // 正常封装的一次数据消息固定头为128，不足则不进行处理

                    // 将接受到的消息转换成文本
                    var textReceivedAll = CommunicationArgs.Encoding.GetString(bytesReceived.ToArray());

                    // 取出固定长度消息头
                    var text128LengthMsgInfo = textReceivedAll.Substring(0, 128);

                    // 判断合法性
                    if (string.IsNullOrEmpty(text128LengthMsgInfo.Trim(char.MinValue)))
                    {
                        // 断开操作
                        socketClient.Close();
                        SocketOffline(socketClient);
                        GC.Collect();
                        break;
                    }
                    // 定义 MessageInfo Json 格式的文本长度
                    int lengthJsonMsgInfo;
                    try
                    {
                        // 将消息头文本转换为长度
                        lengthJsonMsgInfo = Convert.ToInt32(text128LengthMsgInfo);
                    }
                    catch
                    {
                        continue;
                    }

                    // 取出 MessageInfo Json 格式的文本
                    var jsonMsgInfo = textReceivedAll.Substring(128, lengthJsonMsgInfo);
                    // 反序列化出 MessageInfo
                    var messageInfo = Helpers.JsonDeserialize<MessageInfo>(jsonMsgInfo, CommunicationArgs.Encoding);
                    // 解析消息类型
                    switch (messageInfo.MessageType)
                    {
                        case MessageTypes.Text:
                            #region 处理文本类型消息
                            {
                                // 读取出消息内容
                                var textMsg = messageInfo.Length != 0
                                    ? textReceivedAll.Substring(128 + lengthJsonMsgInfo)
                                    : string.Empty;

                                if (messageInfo.ReceiveId == null)
                                {
                                    // 发给服务器处理
                                    if (TextMessageReceived != null)
                                        TextMessageReceived.Invoke(this,
                                            new TextMessageReceivedEventArgs(currentSocketClientContactsInfo, textMsg));
                                }
                                else
                                {
                                    // 自动转发处理
                                    var userInfoReceiveMsg = Contacts.Find(u => u.Id == messageInfo.ReceiveId);
                                    if (userInfoReceiveMsg != null)
                                    {
                                        if (userInfoReceiveMsg.WebSocket)
                                        {
                                            // WebSocket 客户端处理
                                            var bytesSend = PackData(bytesReceived.ToArray());
                                            userInfoReceiveMsg.Socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                                        }
                                        else
                                        {
                                            // 窗体客户端处理
                                            var lengthTextMsg = CommunicationArgs.Encoding.GetByteCount(textMsg);
                                            messageInfo.Length = lengthTextMsg;
                                            var jsonMsgInfo1 = Helpers.JsonSerialize(messageInfo,
                                                CommunicationArgs.Encoding);
                                            var lengthJsonMsgInfo1 =
                                                CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo1);
                                            var text128LengthJsonMsgInfo = lengthJsonMsgInfo1.ToString()
                                                .PadLeft(128, '0');
                                            var bytesSend =
                                                CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo +
                                                                                    jsonMsgInfo1 +
                                                                                    textMsg);
                                            userInfoReceiveMsg.Socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                                        }
                                    }
                                    else
                                    {
                                        // 处理丢弃消息操作
                                    }
                                }
                            }
                            #endregion
                            break;
                        case MessageTypes.File:
                            break;
                        case MessageTypes.UserInfo:
                            #region 处理用户信息类型的消息
                            {
                                var jsonUserInfo = textReceivedAll.Substring(128 + lengthJsonMsgInfo);
                                var userInfo = Helpers.JsonDeserialize<ContactsInfo>(jsonUserInfo,
                                    CommunicationArgs.Encoding);
                                if (ContactsInfoReceived != null)
                                {
                                    if (ContactsInfoReceived.Invoke(this, new ContactsInfoEventArgs(userInfo)))
                                    {
                                        currentSocketClientContactsInfo.Id = userInfo.Id;
                                        currentSocketClientContactsInfo.Name = userInfo.Name;
                                        currentSocketClientContactsInfo.Password = userInfo.Password;
                                        currentSocketClientContactsInfo.TransferFile = userInfo.TransferFile;

                                        var bytesSend = PackData(bytesReceived.ToArray());

                                        socketClient.Send(bytesSend, bytesSend.Length, SocketFlags.None);

                                        if (ContactsConnected != null)
                                            ContactsConnected.Invoke(this,
                                                new ContactsInfoEventArgs(currentSocketClientContactsInfo));

                                        if (!userInfo.TransferFile)
                                        {
                                            var actionDelegate =
                                                new Action<ContactsInfo, MessageTypes>(BroadcastContactsConnected);
                                            actionDelegate.BeginInvoke(currentSocketClientContactsInfo,
                                                MessageTypes.Connected, n =>
                                                    {
                                                        actionDelegate.EndInvoke(n);
                                                        n.AsyncWaitHandle.Close();
                                                    }, null);
                                        }
                                    }
                                    else
                                    {
                                        socketClient.Close();
                                        SocketOffline(socketClient);
                                        GC.Collect();
                                    }
                                }
                                else
                                {
                                    socketClient.Close();
                                    SocketOffline(socketClient);
                                    GC.Collect();
                                }
                            }
                            #endregion
                            break;
                        case MessageTypes.Custom:
                            break;
                        case MessageTypes.Connected:
                            break;
                        case MessageTypes.Offline:
                            break;
                        case MessageTypes.RequestUsers:
                            #region 处理用户列表消息
                            {
                                var jsonUsers = Helpers.JsonSerialize(Contacts.Where(u => !u.TransferFile),
                                    CommunicationArgs.Encoding);
                                var lengthJsonUsers = jsonUsers.Length;
                                var msgInfoSend = new MessageInfo
                                {
                                    Length = lengthJsonUsers,
                                    MessageType = MessageTypes.RequestUsers,
                                    ReceiveId = currentSocketClientContactsInfo.Id,
                                    SendId = null
                                };
                                var jsonMsgInfoSend = Helpers.JsonSerialize(msgInfoSend, CommunicationArgs.Encoding);
                                var lengthJsonMsgInfoSend = jsonMsgInfoSend.Length;
                                var text128LengthJsonMsgInfoSend =
                                    lengthJsonMsgInfoSend.ToString().PadLeft(128, '0');
                                var bytesSend = PackData(text128LengthJsonMsgInfoSend +
                                                         jsonMsgInfoSend + jsonUsers);

                                socketClient.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                            }
                            #endregion
                            break;
                        case MessageTypes.RequestSendFile:
                            break;
                        case MessageTypes.AgreeReceiveFile:
                            break;
                        case MessageTypes.BroadcastText:
                            #region 处理广播消息
                            {
                                var textMsg = messageInfo.Length != 0
                                    ? textReceivedAll.Substring(128 + lengthJsonMsgInfo)
                                    : string.Empty;

                                // 如果服务器有处理文本消息事件，则进行调用
                                if (BroadcastTextMessageReceived != null)
                                    BroadcastTextMessageReceived.Invoke(this,
                                        new TextMessageReceivedEventArgs(currentSocketClientContactsInfo, textMsg));

                                var actionDelegate = new Action<string, string>(BroadcastTextMessageServer);
                                actionDelegate.BeginInvoke(messageInfo.SendId, textMsg, n =>
                                    {
                                        actionDelegate.EndInvoke(n);
                                        n.AsyncWaitHandle.Close();
                                    }, null);
                            }
                            #endregion
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }
                else
                {
                    // 消息固定头部缓冲区
                    var bytesText128LengthMsgInfo = new byte[128];
                    // 开始存入缓冲区的偏移量
                    int startSaveIndex;
                    try
                    {
                        // 循环读取防止在缓冲区较小的时候出现半截消息的情况
                        // 确保读取到整个消息头
                        // 同理：每次读取使用循环确保读取到一次完整的消息
                        startSaveIndex = 0;
                        while (true)
                        {
                            var lengthReceived = socketClient.Receive(bytesText128LengthMsgInfo, startSaveIndex,
                                128 - startSaveIndex, SocketFlags.None);
                            // 根据已经接收到的实际字节数重新计算偏移量
                            startSaveIndex += lengthReceived;
                            // 如果偏移量等于或大于要接收的量，则停止接收
                            if (startSaveIndex >= 128)
                                break;
                        }
                    }
                    catch (SocketException e)
                    {
                        // 表示客户端断开连接，否则抛出异常
                        if (e.ErrorCode != 10054 || e.SocketErrorCode != SocketError.ConnectionReset)
                        {
                            // 表示有系统终止客户端连接
                            if (e.ErrorCode != 10053 || e.SocketErrorCode != SocketError.ConnectionAborted)
                            {
                                throw;
                            }
                        }
                        // 设置 Socket 离线
                        SocketOffline(socketClient);
                        GC.Collect();
                        break;
                    }
                    catch (ObjectDisposedException)
                    {
                        // Socket 已经释放
                        GC.Collect();
                        break;
                    }

                    // 将长度消息头转换为文本
                    var text128LengthMsgInfo = CommunicationArgs.Encoding.GetString(bytesText128LengthMsgInfo);
                    //var text128LengthMsgInfo = Encoding.ASCII.GetString(bytesText128LengthMsgInfo);

                    // 判断消息头是否合法
                    if (string.IsNullOrEmpty(text128LengthMsgInfo.Trim(char.MinValue)))
                    {
                        // 对于发送非法消息客户端进行断开连接操作
                        socketClient.Close();
                        // 设置 Socket 离线
                        SocketOffline(socketClient);
                        GC.Collect();
                        break;
                    }

                    // 定义 MessageInfo 消息的长度
                    int lengthJsonMsgInfo;
                    try
                    {
                        // 将消息头文本转换为长度
                        lengthJsonMsgInfo = Convert.ToInt32(text128LengthMsgInfo);
                    }
                    catch
                    {
                        // 处理 WebSocket 客户端的数据
                        #region 判断是否是 WebSocket 连接，如果是则完成握手操作
                        {
                            if (socketClient.Available != 0)
                            {
                                var bytesWebTitle = new byte[socketClient.Available];
                                socketClient.Receive(bytesWebTitle, SocketFlags.None);
                                var webTetle = text128LengthMsgInfo +
                                               CommunicationArgs.Encoding.GetString(bytesWebTitle);
                                var regex = new Regex("Sec-WebSocket-Key:(.*?)" + Environment.NewLine);
                                var match = regex.Match(webTetle);
                                if (match.Groups.Count != 0)
                                {
                                    var key =
                                        Regex.Replace(match.Value, "Sec-WebSocket-Key:(.*?)", "$1")
                                            .Trim();
                                    currentSocketClientContactsInfo.WebSocketKey = key;
                                    currentSocketClientContactsInfo.WebSocket = true;
                                    currentSocketClientContactsInfo.Id = Helpers.GetGuidToN();
                                    var secKeyAccept =
                                        Helpers.GetTextHashCode(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11",
                                            CommunicationArgs.Encoding);
                                    currentSocketClientContactsInfo.AcceptKey = secKeyAccept;
                                    var stringBuilder = new StringBuilder();
                                    stringBuilder.AppendLine("HTTP/1.1 101 Switching Protocols");
                                    stringBuilder.AppendLine("Connection:Upgrade");
                                    stringBuilder.AppendLine("Upgrade:WebSocket");
                                    stringBuilder.AppendLine("Sec-WebSocket-Accept:" + secKeyAccept);
                                    stringBuilder.AppendLine();

                                    var bytesSend = CommunicationArgs.Encoding.GetBytes(stringBuilder.ToString());
                                    socketClient.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                                }
                            }
                        }
                        #endregion
                        // 出现异常则丢掉，重新开始接收消息
                        // 消息拼接完整理论上不会出现
                        // 出现此情况将导致消息错乱，可能再也接收不到完整的消息了
                        continue;
                    }

                    // MessageInfo 内容缓冲区
                    var bytesJsonMsgInfo = new byte[lengthJsonMsgInfo];
                    startSaveIndex = 0;
                    while (true)
                    {
                        var lengthReceived = socketClient.Receive(bytesJsonMsgInfo, startSaveIndex,
                            lengthJsonMsgInfo - startSaveIndex, SocketFlags.None);
                        startSaveIndex += lengthReceived;
                        if (startSaveIndex >= lengthJsonMsgInfo)
                            break;
                    }

                    // 获取 MessageInfo 的 Json 文本
                    var jsonMsgInfo = CommunicationArgs.Encoding.GetString(bytesJsonMsgInfo);
                    // 将 Json 反序列化为 MessageInfo
                    var messageInfo = Helpers.JsonDeserialize<MessageInfo>(jsonMsgInfo, CommunicationArgs.Encoding);

                    // 解析消息
                    switch (messageInfo.MessageType)
                    {
                        case MessageTypes.Text:
                            #region 处理文本类型消息
                            {
                                // 根据文本长度定义文本缓冲区
                                var bytesText = new byte[messageInfo.Length];
                                // 如果有消息则读取
                                if (messageInfo.Length != 0)
                                {
                                    startSaveIndex = 0;
                                    while (true)
                                    {
                                        var lengthReceived = socketClient.Receive(bytesText, startSaveIndex,
                                            messageInfo.Length - startSaveIndex,
                                            SocketFlags.None);
                                        startSaveIndex += lengthReceived;
                                        if (startSaveIndex >= messageInfo.Length)
                                            break;
                                    }
                                }

                                // 将消息转换为对应的文本
                                var textMsg = messageInfo.Length != 0
                                    ? CommunicationArgs.Encoding.GetString(bytesText)
                                    : string.Empty;

                                if (messageInfo.ReceiveId == null)
                                {
                                    // 没有接收者则表示服务器消息

                                    // 如果服务器有处理文本消息事件，则进行调用
                                    if (TextMessageReceived != null)
                                        TextMessageReceived.Invoke(this,
                                            new TextMessageReceivedEventArgs(currentSocketClientContactsInfo, textMsg));
                                }
                                else
                                {
                                    // 有接收者则自动进行转发到指定的客户端

                                    // 根据 Id 查找接收者
                                    var userInfoReceiveMsg = Contacts.Find(u => u.Id == messageInfo.ReceiveId);

                                    // 如果消息接收者存在则发送，否则丢弃消息
                                    if (userInfoReceiveMsg != null)
                                    {
                                        if (userInfoReceiveMsg.WebSocket)
                                        {
                                            messageInfo.Length = textMsg.Length;
                                            var jsonMsgInfo1 = Helpers.JsonSerialize(messageInfo,
                                                CommunicationArgs.Encoding);
                                            var lengthJsonMsgInfo1 = jsonMsgInfo1.Length;
                                            var text128LengthJsonMsgInfo = lengthJsonMsgInfo1.ToString()
                                                .PadLeft(128, '0');
                                            var bytesSend1 = PackData(text128LengthJsonMsgInfo + jsonMsgInfo1 + textMsg);
                                            userInfoReceiveMsg.Socket.Send(bytesSend1, bytesSend1.Length,
                                                SocketFlags.None);
                                        }
                                        else
                                        {
                                            // 定义发送缓冲区
                                            var bytesSend = new byte[128 + lengthJsonMsgInfo + messageInfo.Length];

                                            // 将消息重新组合拼装到发送缓冲区
                                            // 消息固定长度头
                                            Array.Copy(bytesText128LengthMsgInfo, bytesSend, 128);
                                            // MessageInfo 信息
                                            Array.Copy(bytesJsonMsgInfo, 0, bytesSend, 128, lengthJsonMsgInfo);
                                            // 文本消息
                                            Array.Copy(bytesText, 0, bytesSend, 128 + lengthJsonMsgInfo,
                                                messageInfo.Length);

                                            userInfoReceiveMsg.Socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                                        }
                                    }
                                    else
                                    {
                                        // 处理丢弃消息操作
                                    }
                                }
                            }
                            #endregion
                            break;
                        case MessageTypes.File:
                            #region 处理文件类型消息
                            // 定义文件接收缓冲区
                            var bytesFile = new byte[messageInfo.Length];
                            // 如果含有文件内容则读取
                            if (messageInfo.Length != 0)
                            {
                                startSaveIndex = 0;
                                while (true)
                                {
                                    var lengthReceived = socketClient.Receive(bytesFile, startSaveIndex,
                                        messageInfo.Length - startSaveIndex,
                                        SocketFlags.None);

                                    startSaveIndex += lengthReceived;
                                    if (startSaveIndex >= messageInfo.Length)
                                        break;
                                }
                            }

                            if (messageInfo.ReceiveId == null)
                            {
                                // 如果没有接收者则代表服务器

                                // 如果有处理文件消息事件则调用
                                if (FileMessageReceived != null)
                                {
                                    FileMessageReceived.Invoke(this,
                                        new FileMessageReceivedEventArgs(currentSocketClientContactsInfo,
                                            messageInfo.TransferFileInfo,
                                            bytesFile));
                                }
                            }
                            else
                            {
                                // 如果有接收者则自动转发到指定客户端

                                // 定义发送缓冲区
                                var bytesSend = new byte[128 + lengthJsonMsgInfo + messageInfo.Length];

                                Array.Copy(bytesText128LengthMsgInfo, bytesSend, 128);
                                Array.Copy(bytesJsonMsgInfo, 0, bytesSend, 128, bytesJsonMsgInfo.Length);
                                Array.Copy(bytesFile, 0, bytesSend, 128 + bytesJsonMsgInfo.Length,
                                    bytesFile.Length);

                                var userInfoReceiveMsg =
                                    Contacts.Find(u => u.Id == messageInfo.TransferFileInfo.ReceiveId);
                                if (userInfoReceiveMsg != null && !userInfoReceiveMsg.WebSocket)
                                {
                                    userInfoReceiveMsg.Socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                                }
                                else
                                {
                                    // 处理丢弃消息操作
                                }
                            }
                            #endregion
                            break;
                        case MessageTypes.UserInfo:
                            #region 处理用户信息类型的消息
                            {
                                var bytesJsonUserInfo = new byte[messageInfo.Length];
                                if (messageInfo.Length != 0)
                                {
                                    startSaveIndex = 0;
                                    while (true)
                                    {
                                        var lengthReceived = socketClient.Receive(bytesJsonUserInfo, startSaveIndex,
                                            messageInfo.Length - startSaveIndex,
                                            SocketFlags.None);
                                        startSaveIndex += lengthReceived;
                                        if (startSaveIndex >= messageInfo.Length)
                                            break;
                                    }
                                }
                                var jsonUserInfo = CommunicationArgs.Encoding.GetString(bytesJsonUserInfo);
                                var userInfo = Helpers.JsonDeserialize<ContactsInfo>(jsonUserInfo,
                                    CommunicationArgs.Encoding);

                                if (ContactsInfoReceived != null)
                                {
                                    if (ContactsInfoReceived.Invoke(this, new ContactsInfoEventArgs(userInfo)))
                                    {
                                        currentSocketClientContactsInfo.Id = userInfo.Id;
                                        currentSocketClientContactsInfo.Name = userInfo.Name;
                                        currentSocketClientContactsInfo.Password = userInfo.Password;
                                        currentSocketClientContactsInfo.TransferFile = userInfo.TransferFile;
                                        currentSocketClientContactsInfo.LocalEndPointByClient = userInfo.LocalEndPointByClient;
                                        currentSocketClientContactsInfo.RemoteEndPointByClient = userInfo.RemoteEndPointByClient;

                                        var bytesSend = new byte[128 + bytesJsonMsgInfo.Length];
                                        Array.Copy(bytesText128LengthMsgInfo, bytesSend, 128);
                                        Array.Copy(bytesJsonMsgInfo, 0, bytesSend, 128, bytesJsonMsgInfo.Length);

                                        socketClient.Send(bytesSend);

                                        if (ContactsConnected != null)
                                            ContactsConnected.Invoke(this,
                                                new ContactsInfoEventArgs(currentSocketClientContactsInfo));

                                        if (!userInfo.TransferFile)
                                        {
                                            var actionDelegate =
                                                new Action<ContactsInfo, MessageTypes>(BroadcastContactsConnected);
                                            actionDelegate.BeginInvoke(currentSocketClientContactsInfo,
                                                MessageTypes.Connected, n =>
                                                    {
                                                        actionDelegate.EndInvoke(n);
                                                        n.AsyncWaitHandle.Close();
                                                    }, null);
                                        }
                                    }
                                    else
                                    {
                                        socketClient.Close();
                                        SocketOffline(socketClient);
                                        GC.Collect();
                                    }
                                }
                                else
                                {
                                    socketClient.Close();
                                    SocketOffline(socketClient);
                                    GC.Collect();
                                }
                            }
                            #endregion
                            break;
                        case MessageTypes.RequestUsers:
                            #region 处理用户列表消息
                            {
                                var jsonUsers = Helpers.JsonSerialize(Contacts.Where(u => !u.TransferFile),
                                    CommunicationArgs.Encoding);
                                var lengthJsonUsers = CommunicationArgs.Encoding.GetByteCount(jsonUsers);
                                var msgInfoSend = new MessageInfo
                                {
                                    Length = lengthJsonUsers,
                                    MessageType = MessageTypes.RequestUsers,
                                    ReceiveId = currentSocketClientContactsInfo.Id,
                                    SendId = null
                                };
                                var jsonMsgInfoSend = Helpers.JsonSerialize(msgInfoSend, CommunicationArgs.Encoding);
                                var lengthJsonMsgInfoSend = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfoSend);
                                var text128LengthJsonMsgInfoSend =
                                    lengthJsonMsgInfoSend.ToString().PadLeft(128, '0');
                                var bytesSend =
                                    CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfoSend +
                                                                        jsonMsgInfoSend + jsonUsers);

                                socketClient.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                            }
                            #endregion
                            break;
                        case MessageTypes.Custom:
                            break;
                        case MessageTypes.Connected:
                            break;
                        case MessageTypes.Offline:
                            break;
                        case MessageTypes.RequestSendFile:
                            #region 处理请求发送文件消息
                            {
                                if (messageInfo.ReceiveId == null)
                                {
                                    // 请求给服务端发送文件
                                    if (RequestSendFile != null)
                                    {
                                        RequestSendFile.Invoke(this,
                                            new FileMessageReceivedEventArgs(currentSocketClientContactsInfo,
                                                messageInfo.TransferFileInfo, null));
                                    }
                                }
                                else
                                {
                                    var bytesSend = new byte[128 + lengthJsonMsgInfo];

                                    Array.Copy(bytesText128LengthMsgInfo, bytesSend, 128);
                                    Array.Copy(bytesJsonMsgInfo, 0, bytesSend, 128, lengthJsonMsgInfo);

                                    var userInfoReceiveMsg = Contacts.Find(u => u.Id == messageInfo.ReceiveId);
                                    if (userInfoReceiveMsg != null && !userInfoReceiveMsg.WebSocket)
                                    {
                                        userInfoReceiveMsg.Socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                                    }
                                    else
                                    {
                                        // 处理丢弃消息操作
                                        messageInfo.TransferFileInfo.Agree = false;
                                        messageInfo.MessageType = MessageTypes.AgreeReceiveFile;

                                        var jsonMessageInfo = Helpers.JsonSerialize(messageInfo,
                                            CommunicationArgs.Encoding);
                                        var lengthJsonMessageInfo =
                                            CommunicationArgs.Encoding.GetByteCount(jsonMessageInfo);
                                        var text128LengthJsonMsgInfo = lengthJsonMessageInfo.ToString()
                                            .PadLeft(128, '0');
                                        var bytesSend1 =
                                            CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo +
                                                                                jsonMessageInfo);

                                        socketClient.Send(bytesSend1, bytesSend1.Length, SocketFlags.None);
                                    }
                                }
                            }
                            #endregion
                            break;
                        case MessageTypes.AgreeReceiveFile:
                            #region 处理同意接收文件消息
                            {
                                if (messageInfo.ReceiveId == null)
                                {
                                    // 请求给服务端发送文件
                                    if (AgreeReceiveFile != null)
                                    {
                                        AgreeReceiveFile.Invoke(this,
                                            new FileMessageReceivedEventArgs(currentSocketClientContactsInfo,
                                                messageInfo.TransferFileInfo, null));
                                    }
                                }
                                else
                                {
                                    var bytesSend = new byte[128 + lengthJsonMsgInfo];

                                    Array.Copy(bytesText128LengthMsgInfo, bytesSend, 128);
                                    Array.Copy(bytesJsonMsgInfo, 0, bytesSend, 128, (long)lengthJsonMsgInfo);

                                    var userInfoReceiveMsg = Contacts.Find(u => u.Id == messageInfo.ReceiveId);
                                    if (userInfoReceiveMsg != null)
                                    {
                                        userInfoReceiveMsg.Socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                                    }
                                }
                            }
                            #endregion
                            break;
                        case MessageTypes.BroadcastText:
                            #region 处理广播消息
                            {
                                // 根据文本长度定义文本缓冲区
                                var bytesText = new byte[messageInfo.Length];
                                // 如果有消息则读取
                                if (messageInfo.Length != 0)
                                {
                                    startSaveIndex = 0;
                                    while (true)
                                    {
                                        var lengthReceived = socketClient.Receive(bytesText, startSaveIndex,
                                            messageInfo.Length - startSaveIndex,
                                            SocketFlags.None);
                                        startSaveIndex += lengthReceived;
                                        if (startSaveIndex >= messageInfo.Length)
                                            break;
                                    }
                                }

                                var textMsg = messageInfo.Length != 0
                                    ? CommunicationArgs.Encoding.GetString(bytesText)
                                    : string.Empty;

                                // 如果服务器有处理文本消息事件，则进行调用
                                if (BroadcastTextMessageReceived != null)
                                    BroadcastTextMessageReceived.Invoke(this,
                                        new TextMessageReceivedEventArgs(currentSocketClientContactsInfo, textMsg));

                                var actionDelegate = new Action<string, string>(BroadcastTextMessageServer);
                                actionDelegate.BeginInvoke(messageInfo.SendId, textMsg, n =>
                                    {
                                        var deletate = (Action<string, string>)((AsyncResult)n).AsyncDelegate;
                                        deletate.EndInvoke(n);
                                        n.AsyncWaitHandle.Close();
                                    }, null);
                            }
                            #endregion
                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }
            }
        }

        /// <summary>
        /// 当有 Socket 下线时处理
        /// </summary>
        /// <param name="socket">需要下线的 Socket</param>
        private void SocketOffline(Socket socket)
        {
            var userInfo = Contacts.Find(u => u.Socket == socket);
            if (userInfo != null)
            {
                Contacts.Remove(userInfo);
                if (ContactsOffline != null)
                    ContactsOffline.Invoke(this, new ContactsInfoEventArgs(userInfo));
                var actionDelegate = new Action<ContactsInfo, MessageTypes>(BroadcastContactsConnected);
                actionDelegate.BeginInvoke(userInfo, MessageTypes.Offline, n =>
                {
                    actionDelegate.EndInvoke(n);
                    n.AsyncWaitHandle.Close();
                }, null);
            }
            else
            {
                socket.Close();
            }
        }

        /// <summary>
        /// 发送文本消息
        /// </summary>
        /// <param name="receiveId">发送到客户端</param>
        /// <param name="sendId">发送者</param>
        /// <param name="text">消息内容</param>
        public bool SendTextMessage(string receiveId, string sendId, string text)
        {
            var lengthText = CommunicationArgs.Encoding.GetByteCount(text);
            var msgInfo = new MessageInfo
            {
                Length = lengthText,
                MessageType = MessageTypes.Text,
                ReceiveId = receiveId,
                SendId = sendId
            };
            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');
            var bytesSend = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo + text);

            if (bytesSend.Length > _socket.SendBufferSize)
            {
                ErrorInfo = "消息长度太长了！";
                ErrorCode = CommunicationErrors.MessageTooLong;
                return false;
            }

            _socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
            return true;
        }

        /// <summary>
        /// 发送文件
        /// </summary>
        /// <param name="receiveId">发送到客户端</param>
        /// <param name="sendId">发送者</param>
        /// <param name="sendFileInfo">发送文件信息</param>
        /// <param name="bytes">表示文件缓冲区</param>
        public bool SendFileMessage(string receiveId, string sendId, TransferFileInfo sendFileInfo, byte[] bytes)
        {
            if (sendFileInfo == null) throw new ArgumentNullException("sendFileInfo");
            if (bytes == null) throw new ArgumentNullException("bytes");
            var lengthBytes = bytes.Length;
            var msgInfo = new MessageInfo
            {
                Length = lengthBytes,
                MessageType = MessageTypes.File,
                ReceiveId = receiveId,
                SendId = sendId,
                TransferFileInfo = sendFileInfo
            };
            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');
            var bytesLengthAndMsgInfo = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo);
            var bytesSend = new byte[bytesLengthAndMsgInfo.Length + lengthBytes];
            Array.Copy(bytesLengthAndMsgInfo, bytesSend, bytesLengthAndMsgInfo.Length);
            Array.Copy(bytes, 0, bytesSend, bytesLengthAndMsgInfo.Length, bytes.Length);

            if (bytesSend.Length > _socket.SendBufferSize)
            {
                ErrorInfo = "消息长度太长了！";
                ErrorCode = CommunicationErrors.MessageTooLong;
                return false;
            }

            _socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
            return true;
        }

        /// <summary>
        /// 发送用户信息到服务器
        /// </summary>
        /// <param name="user">用户信息</param>
        /// <exception cref="ArgumentNullException">如果 user 为空，则将引发此异常。</exception>
        public void SendUserInfoMessage(ContactsInfo user)
        {
            if (user == null) throw new ArgumentNullException("user");

            var jsonUserInfo = Helpers.JsonSerialize(user, CommunicationArgs.Encoding);
            var lengthJsonUserInfo = CommunicationArgs.Encoding.GetByteCount(jsonUserInfo);
            var msgInfo = new MessageInfo
            {
                SendId = user.Id,
                Length = lengthJsonUserInfo,
                MessageType = MessageTypes.UserInfo
            };
            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');

            var bytesSend = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo + jsonUserInfo);

            _socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
        }

        /// <summary>
        /// 请求用户列表
        /// </summary>
        public void SendRequestUsersMessage()
        {
            var msgInfo = new MessageInfo { MessageType = MessageTypes.RequestUsers };

            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');
            var bytesSend = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo);

            _socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
        }

        /// <summary>
        /// 请求发送文件
        /// </summary>
        /// <param name="receiveId">接收方</param>
        /// <param name="sendId">发送方</param>
        /// <param name="sendFileInfo">文件信息</param>
        public void SendRequestSendFileMessage(string receiveId, string sendId, TransferFileInfo sendFileInfo)
        {
            var msgInfo = new MessageInfo
            {
                Length = 0,
                MessageType = MessageTypes.RequestSendFile,
                ReceiveId = receiveId,
                SendId = sendId,
                TransferFileInfo = sendFileInfo
            };
            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');
            var bytesSend = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo);

            _socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
        }

        /// <summary>
        /// 同意接收文件
        /// </summary>
        /// <param name="receiveId">接收方</param>
        /// <param name="sendId">发送方</param>
        /// <param name="sendFileInfo">文件信息</param>
        public void SendAgreeReceiveFileMessage(string receiveId, string sendId, TransferFileInfo sendFileInfo)
        {
            var msgInfo = new MessageInfo
            {
                Length = 0,
                MessageType = MessageTypes.AgreeReceiveFile,
                ReceiveId = receiveId,
                SendId = sendId,
                TransferFileInfo = sendFileInfo
            };
            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');
            var bytesSend = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo);

            _socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
        }

        /// <summary>
        /// 群发消息
        /// </summary>
        /// <param name="user">用户信息</param>
        /// <param name="type">消息类型（上线或下线）</param>
        public void BroadcastContactsConnected(ContactsInfo user, MessageTypes type)
        {
            var jsonUserInfo = Helpers.JsonSerialize(user, CommunicationArgs.Encoding);
            var lengthJsonUserInfo = CommunicationArgs.Encoding.GetByteCount(jsonUserInfo);
            var msgInfo = new MessageInfo
            {
                Length = lengthJsonUserInfo,
                MessageType = type
            };
            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');
            var bytesSend = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo + jsonUserInfo);

            var msgInfoForWeb = new MessageInfo
            {
                Length = jsonUserInfo.Length,
                MessageType = type
            };
            var jsonMsgInfoForWeb = Helpers.JsonSerialize(msgInfoForWeb, CommunicationArgs.Encoding);
            var lengthJsonMsgInfoForWeb = jsonMsgInfoForWeb.Length;
            var text128LengthJsonMsgInfoForWeb = lengthJsonMsgInfoForWeb.ToString().PadLeft(128, '0');
            var bytesSendForWeb = PackData(text128LengthJsonMsgInfoForWeb + jsonMsgInfo + jsonUserInfo);

            var list = new List<ContactsInfo>(Contacts);

            lock (list)
            {
                list.ForEach(u =>
                {
                    if (u == null || !u.Socket.Connected) return;
                    try
                    {
                        if (u.WebSocket)
                        {
                            u.Socket.Send(bytesSendForWeb, bytesSendForWeb.Length, SocketFlags.None);
                        }
                        else
                        {
                            u.Socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                        }
                    }
                    catch (SocketException)
                    {
                        if (!u.Socket.Connected)
                            throw;
                    }
                });
            }
        }

        /// <summary>
        /// 广播文本消息
        /// </summary>
        /// <param name="sendId">发送者 Id</param>
        /// <param name="text">文本内容</param>
        /// <returns>True 成功，False 失败。</returns>
        public bool BroadcastTextMessage(string sendId, string text)
        {
            var lengthText = CommunicationArgs.Encoding.GetByteCount(text);
            var msgInfo = new MessageInfo
            {
                Length = lengthText,
                MessageType = MessageTypes.BroadcastText,
                ReceiveId = null,
                SendId = sendId
            };
            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');
            var bytesSend = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo + text);

            if (bytesSend.Length > _socket.SendBufferSize)
            {
                ErrorInfo = "消息长度太长了！";
                ErrorCode = CommunicationErrors.MessageTooLong;
                return false;
            }

            _socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
            return true;
        }

        /// <summary>
        /// 广播文本消息
        /// </summary>
        /// <param name="sendId">发送者 Id</param>
        /// <param name="text">文本内容</param>
        /// <returns>True 成功，False 失败。</returns>
        public void BroadcastTextMessageServer(string sendId, string text)
        {
            var lengthText = CommunicationArgs.Encoding.GetByteCount(text);
            var msgInfo = new MessageInfo
            {
                Length = lengthText,
                MessageType = MessageTypes.BroadcastText,
                ReceiveId = null,
                SendId = sendId
            };
            var jsonMsgInfo = Helpers.JsonSerialize(msgInfo, CommunicationArgs.Encoding);
            var lengthJsonMsgInfo = CommunicationArgs.Encoding.GetByteCount(jsonMsgInfo);
            var text128LengthJsonMsgInfo = lengthJsonMsgInfo.ToString().PadLeft(128, '0');
            var bytesSend = CommunicationArgs.Encoding.GetBytes(text128LengthJsonMsgInfo + jsonMsgInfo + text);

            var msgInfoForWeb = new MessageInfo
            {
                Length = text.Length,
                MessageType = MessageTypes.BroadcastText,
                ReceiveId = null,
                SendId = sendId
            };
            var jsonMsgInfoForWeb = Helpers.JsonSerialize(msgInfoForWeb, CommunicationArgs.Encoding);
            var lengthJsonMsgInfoForWeb = jsonMsgInfoForWeb.Length;
            var text128LengthJsonMsgInfoForWeb = lengthJsonMsgInfoForWeb.ToString().PadLeft(128, '0');
            var bytesSendForWeb = PackData(text128LengthJsonMsgInfoForWeb + jsonMsgInfo + text);

            lock (Contacts)
            {
                Contacts.ForEach(u =>
                {
                    if (u == null || !u.Socket.Connected || u.Id == sendId) return;
                    try
                    {
                        if (u.WebSocket)
                        {
                            u.Socket.Send(bytesSendForWeb, bytesSendForWeb.Length, SocketFlags.None);
                        }
                        else
                        {
                            u.Socket.Send(bytesSend, bytesSend.Length, SocketFlags.None);
                        }
                    }
                    catch (SocketException)
                    {
                        if (!u.Socket.Connected)
                            throw;
                    }
                });
            }
        }

        /// <summary>
        /// 连接服务端
        /// </summary>
        public bool Connect()
        {
            if (_communicationMode == CommunicationModes.TcpClient && !_socket.Connected)
            {
                try
                {
                    _socket.Connect(CommunicationArgs.EndPoint);
                }
                catch (Exception e)
                {
                    ErrorInfo = e.Message;
                    ErrorCode = CommunicationErrors.CommunicationError;
                    return false;
                }
                ThreadPool.QueueUserWorkItem(ClientReceive, _socket);
                IsRuning = true;
                if (IsRuningChanged != null)
                {
                    IsRuningChanged.Invoke(IsRuning);
                }
                return true;
            }

            ErrorInfo = "当前通信对象不支持连接操作。";
            ErrorCode = CommunicationErrors.ModeMismatching;
            return false;
        }

        /// <summary>
        /// 客户端收到消息处理
        /// </summary>
        /// <param name="obj">Socket 对象</param>
        private void ClientReceive(object obj)
        {
            if (obj == null)
            {
                return;
            }
            var socket = (Socket)obj;
            while (true)
            {
                try
                {
                    GC.Collect();
                    var bytesText128LengthMsgInfo = new byte[128];
                    int startSaveIndex;
                    try
                    {
                        startSaveIndex = 0;
                        while (true)
                        {
                            var lengthReceived = socket.Receive(bytesText128LengthMsgInfo, startSaveIndex,
                                128 - startSaveIndex, SocketFlags.None);
                            startSaveIndex += lengthReceived;
                            if (startSaveIndex >= 128)
                                break;
                        }
                    }
                    catch (SocketException e)
                    {
                        if (e.ErrorCode == 10053 && e.SocketErrorCode == SocketError.ConnectionAborted)
                        {
                            GC.Collect();
                            IsRuning = false;
                            if (IsRuningChanged != null)
                            {
                                IsRuningChanged.Invoke(IsRuning);
                            }
                            break; // 客户端下线
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        GC.Collect();
                        IsRuning = false;
                        if (IsRuningChanged != null)
                        {
                            IsRuningChanged.Invoke(IsRuning);
                        }
                        break; // 客户端下线
                    }
                    var text128LengthMsgInfo = CommunicationArgs.Encoding.GetString(bytesText128LengthMsgInfo);

                    if (string.IsNullOrEmpty(text128LengthMsgInfo.Trim(char.MinValue)))
                    {
                        socket.Close();

                        // 服务端断开
                        IsRuning = false;
                        if (IsRuningChanged != null)
                        {
                            IsRuningChanged.Invoke(IsRuning);
                        }

                        GC.Collect();
                        break; // 客户端下线
                    }
                    int lengthJsonMsgInfo;
                    try
                    {
                        lengthJsonMsgInfo = Convert.ToInt32(text128LengthMsgInfo);
                    }
                    catch
                    {
                        continue;
                    }
                    var bytesJsonMsgInfo = new byte[lengthJsonMsgInfo];
                    startSaveIndex = 0;
                    while (true)
                    {
                        var lengthReceived = socket.Receive(bytesJsonMsgInfo, startSaveIndex,
                            lengthJsonMsgInfo - startSaveIndex, SocketFlags.None);
                        startSaveIndex += lengthReceived;
                        if (startSaveIndex >= lengthJsonMsgInfo)
                            break;
                    }

                    var jsonMsgInfo = CommunicationArgs.Encoding.GetString(bytesJsonMsgInfo);
                    var msgInfo = Helpers.JsonDeserialize<MessageInfo>(jsonMsgInfo, CommunicationArgs.Encoding);
                    var userInfoFromMsg = Contacts.Find(u => u.Id == msgInfo.SendId) ??
                                          new ContactsInfo { Id = msgInfo.SendId };

                    switch (msgInfo.MessageType)
                    {
                        case MessageTypes.Text:

                            #region 处理文本类型消息

                            {
                                var bytesText = new byte[msgInfo.Length];
                                if (msgInfo.Length != 0)
                                {
                                    startSaveIndex = 0;
                                    while (true)
                                    {
                                        var lengthReceived = socket.Receive(bytesText, startSaveIndex,
                                            msgInfo.Length - startSaveIndex,
                                            SocketFlags.None);
                                        startSaveIndex += lengthReceived;
                                        if (startSaveIndex >= msgInfo.Length)
                                            break;
                                    }
                                }

                                if (TextMessageReceived != null)
                                {
                                    var textMsg = msgInfo.Length != 0
                                        ? CommunicationArgs.Encoding.GetString(bytesText)
                                        : string.Empty;

                                    TextMessageReceived.Invoke(this,
                                        new TextMessageReceivedEventArgs(userInfoFromMsg, textMsg));
                                }
                            }

                            #endregion

                            break;
                        case MessageTypes.File:

                            #region 处理文件类型信息

                            var bytesFile = new byte[msgInfo.Length];
                            if (msgInfo.Length != 0)
                            {
                                startSaveIndex = 0;
                                while (true)
                                {
                                    var lengthReceived = socket.Receive(bytesFile, startSaveIndex,
                                        msgInfo.Length - startSaveIndex,
                                        SocketFlags.None);
                                    startSaveIndex += lengthReceived;
                                    if (startSaveIndex >= msgInfo.Length)
                                        break;
                                }
                            }

                            if (FileMessageReceived != null)
                            {
                                FileMessageReceived.Invoke(this,
                                    new FileMessageReceivedEventArgs(userInfoFromMsg, msgInfo.TransferFileInfo, bytesFile));
                            }

                            #endregion

                            break;
                        case MessageTypes.Connected:

                            #region 处理上线信息

                            {
                                var bytesJsonUserInfo = new byte[msgInfo.Length];
                                if (msgInfo.Length != 0)
                                {
                                    startSaveIndex = 0;
                                    while (true)
                                    {
                                        var lengthReceived = socket.Receive(bytesJsonUserInfo, startSaveIndex,
                                            msgInfo.Length - startSaveIndex,
                                            SocketFlags.None);
                                        startSaveIndex += lengthReceived;
                                        if (startSaveIndex >= msgInfo.Length)
                                            break;
                                    }

                                    var jsonUserInfo = CommunicationArgs.Encoding.GetString(bytesJsonUserInfo);
                                    var userInfo = Helpers.JsonDeserialize<ContactsInfo>(jsonUserInfo,
                                        CommunicationArgs.Encoding);

                                    AddContacts(userInfo);
                                }
                            }

                            #endregion

                            break;
                        case MessageTypes.Offline:

                            #region 处理下线信息

                            {
                                var bytesJsonUserInfo = new byte[msgInfo.Length];
                                if (msgInfo.Length != 0)
                                {
                                    startSaveIndex = 0;
                                    while (true)
                                    {
                                        var lengthReceived = socket.Receive(bytesJsonUserInfo, startSaveIndex,
                                            msgInfo.Length - startSaveIndex,
                                            SocketFlags.None);
                                        startSaveIndex += lengthReceived;
                                        if (startSaveIndex >= msgInfo.Length)
                                            break;
                                    }

                                    var jsonUserInfo = CommunicationArgs.Encoding.GetString(bytesJsonUserInfo);
                                    var userInfo = Helpers.JsonDeserialize<ContactsInfo>(jsonUserInfo,
                                        CommunicationArgs.Encoding);

                                    if (!userInfo.TransferFile)
                                    {
                                        RemoveContacts(userInfo);
                                    }
                                    else
                                    {
                                        // 处理发送文件用户下线事件
                                        if (TransferFileUserOffline != null)
                                            TransferFileUserOffline.Invoke(this, new ContactsInfoEventArgs(userInfo));
                                    }
                                }
                            }

                            #endregion

                            break;
                        case MessageTypes.RequestUsers:

                            #region 处理用户列表信息

                            var bytesJsonUsers = new byte[msgInfo.Length];
                            if (msgInfo.Length != 0)
                            {
                                startSaveIndex = 0;
                                while (true)
                                {
                                    var lengthReceived = socket.Receive(bytesJsonUsers, startSaveIndex,
                                        msgInfo.Length - startSaveIndex,
                                        SocketFlags.None);
                                    startSaveIndex += lengthReceived;
                                    if (startSaveIndex >= msgInfo.Length)
                                        break;
                                }

                                var jsonUsers = CommunicationArgs.Encoding.GetString(bytesJsonUsers);

                                var users = Helpers.JsonDeserialize<List<ContactsInfo>>(jsonUsers,
                                    CommunicationArgs.Encoding);
                                if (Contacts == null)
                                    Contacts = new List<ContactsInfo>();

                                Contacts.Clear();
                                Contacts.AddRange(users);

                                if (UpdateContactsComplete != null)
                                    UpdateContactsComplete.Invoke();
                            }

                            #endregion

                            break;
                        case MessageTypes.UserInfo:

                            #region 处理自己的用户信息

                            if (OwnUserInfoReceived != null)
                            {
                                OwnUserInfoReceived.Invoke(msgInfo.SendId);
                            }

                            #endregion

                            break;
                        case MessageTypes.Custom:
                            break;
                        case MessageTypes.RequestSendFile:

                            #region 处理请求发送文件消息

                            if (RequestSendFile != null)
                            {
                                RequestSendFile.Invoke(this,
                                    new FileMessageReceivedEventArgs(userInfoFromMsg, msgInfo.TransferFileInfo, null));
                            }
                            else
                            {
                                msgInfo.TransferFileInfo.Agree = false;
                                SendAgreeReceiveFileMessage(userInfoFromMsg.Id, msgInfo.ReceiveId, msgInfo.TransferFileInfo);
                            }

                            #endregion

                            break;
                        case MessageTypes.AgreeReceiveFile:

                            #region 处理同意接受文件消息

                            if (AgreeReceiveFile != null)
                            {
                                AgreeReceiveFile.Invoke(this,
                                    new FileMessageReceivedEventArgs(userInfoFromMsg, msgInfo.TransferFileInfo, null));
                            }

                            #endregion

                            break;
                        case MessageTypes.BroadcastText:

                            #region 处理广播消息

                            {
                                // 根据文本长度定义文本缓冲区
                                var bytesText = new byte[msgInfo.Length];
                                // 如果有消息则读取
                                if (msgInfo.Length != 0)
                                {
                                    startSaveIndex = 0;
                                    while (true)
                                    {
                                        var lengthReceived = socket.Receive(bytesText, startSaveIndex,
                                            msgInfo.Length - startSaveIndex,
                                            SocketFlags.None);
                                        startSaveIndex += lengthReceived;
                                        if (startSaveIndex >= msgInfo.Length)
                                            break;
                                    }
                                }

                                var textMsg = msgInfo.Length != 0
                                    ? CommunicationArgs.Encoding.GetString(bytesText)
                                    : string.Empty;

                                // 如果服务器有处理文本消息事件，则进行调用
                                if (BroadcastTextMessageReceived != null)
                                    BroadcastTextMessageReceived.Invoke(this,
                                        new TextMessageReceivedEventArgs(userInfoFromMsg, textMsg));
                            }

                            #endregion

                            break;
                        default:
                            throw new ArgumentOutOfRangeException();
                    }
                }
                catch (ObjectDisposedException)
                {
                    break;
                }
            }
        }

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="user">用户信息</param>
        public void AddContacts(ContactsInfo user)
        {
            if (Contacts == null) Contacts = new List<ContactsInfo>();
            var u = Contacts.Find(n => n.Id == user.Id);
            if (u != null) return;
            Contacts.Add(user);
            if (ContactsConnected != null)
                ContactsConnected.Invoke(this, new ContactsInfoEventArgs(user));
        }

        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="user">用户信息</param>
        public void RemoveContacts(ContactsInfo user)
        {
            if (Contacts == null) Contacts = new List<ContactsInfo>();
            var u = Contacts.Find(n => n.Id == user.Id);
            if (u == null) return;
            Contacts.Remove(u);
            if (ContactsOffline != null)
                ContactsOffline.Invoke(this, new ContactsInfoEventArgs(user));
        }

        /// <summary>
        /// 关闭当前 Socket 对象
        /// </summary>
        public void Close()
        {
            _socket.Close();
            _socket = null;

            IsRuning = false;
            if (IsRuningChanged != null)
            {
                IsRuningChanged.Invoke(IsRuning);
            }

            GC.Collect();
            _communicationMode = CommunicationModes.Unknown;
        }

        /// <summary>
        /// 关闭指定客户端
        /// </summary>
        /// <param name="id">客户端 Id</param>
        public void DisconnectClient(string id)
        {
            if (string.IsNullOrEmpty(id) || id.Trim() == string.Empty)
                return;

            var user = Contacts.Find(n => n.Id == id);
            if (user != null)
            {
                user.Socket.Close();
            }
        }

        /// <summary>
        /// 更新联系人列表成功
        /// </summary>
        [Description("当更新好友列表成功时发生")]
        public event Action UpdateContactsComplete;

        /// <summary>
        /// 收到文本消息事件
        /// </summary>
        [Description("当收到文本消息时发生")]
        public event EventHandler<TextMessageReceivedEventArgs> TextMessageReceived;

        /// <summary>
        /// 收到文件消息事件
        /// </summary>
        [Description("当收到文件消息时发生")]
        public event EventHandler<FileMessageReceivedEventArgs> FileMessageReceived;

        /// <summary>
        /// 用户上线事件
        /// </summary>
        [Description("当有新用户上线时发生")]
        public event EventHandler<ContactsInfoEventArgs> ContactsConnected;

        /// <summary>
        /// 用户下线事件
        /// </summary>
        [Description("当有新用户下线时发生")]
        public event EventHandler<ContactsInfoEventArgs> ContactsOffline;

        /// <summary>
        /// 收到发送文件请求事件
        /// </summary>
        [Description("当收到发送文件请求时发生")]
        public event EventHandler<FileMessageReceivedEventArgs> RequestSendFile;

        /// <summary>
        /// 收到同意接收文件事件
        /// </summary>
        [Description("当收到同意接收文件时发生")]
        public event EventHandler<FileMessageReceivedEventArgs> AgreeReceiveFile;

        /// <summary>
        /// 收到自己的用户信息
        /// </summary>
        [Description("当收到自己的用户信息时发生")]
        public event Action<string> OwnUserInfoReceived;

        /// <summary>
        /// 收到用户信息事件
        /// </summary>
        [Description("当收到用户信息时发生")]
        public event EventHandler<ContactsInfoEventArgs, bool> ContactsInfoReceived;

        /// <summary>
        /// 运行状态改变事件
        /// </summary>
        [Description("当运行状态改变时发生")]
        public event Action<bool> IsRuningChanged;

        /// <summary>
        /// 传送文件用户下线事件
        /// </summary>
        [Description("当传送文件用户下线时发生")]
        public event EventHandler<ContactsInfoEventArgs> TransferFileUserOffline;

        /// <summary>
        /// 收到广播文本事件
        /// </summary>
        [Description("当收到广播文本时发生")]
        public event EventHandler<TextMessageReceivedEventArgs> BroadcastTextMessageReceived;

        /// <summary>
        /// 释放当前对象
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 释放由 System.Net.Sockets.Socket 使用的非托管资源，并可根据需要释放托管资源。
        /// </summary>
        /// <param name="disposing">如果为 true，则释放托管资源和非托管资源；如果为 false，则仅释放非托管资源。</param>
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;
            if (disposing)
            {
                if (_socket != null)
                {
                    ((IDisposable)_socket).Dispose();
                }
            }
            _disposed = true;
        }

        /// <summary>
        /// 解析 WebSocket 的消息
        /// </summary>
        /// <param name="bytes">消息缓冲区</param>
        /// <param name="length">接收的长度</param>
        /// <returns></returns>
        private string ParsingWebSocketData(byte[] bytes, int length)
        {
            // 参考：https://my.oschina.net/u/1266171/blog/357488
            if (length < 2)
                return string.Empty;

            var fin = (bytes[0] & 0x80) == 0x80; // 1bit，1表示最后一帧
            if (!fin)
            {
                return string.Empty; //超过一帧暂不处理
            }

            var maskFlag = (bytes[1] & 0x80) == 0x80; // 是否包含掩码
            if (!maskFlag)
            {
                return string.Empty; // 不包含掩码的暂不处理
            }

            var payloadLen = bytes[1] & 0x7F; // 数据长度
            var masks = new byte[4];
            byte[] payloadData;
            if (payloadLen == 126)
            {
                Array.Copy(bytes, 4, masks, 0, 4);
                payloadLen = (ushort)(bytes[2] << 8 | bytes[3]);
                payloadData = new byte[payloadLen];
                Array.Copy(bytes, 8, payloadData, 0, payloadLen);
            }
            else if (payloadLen == 127)
            {
                Array.Copy(bytes, 10, masks, 0, 4);
                var uInt64Bytes = new byte[8];
                for (var i = 0; i < 8; i++)
                {
                    uInt64Bytes[i] = bytes[9 - i];
                }
                var len = BitConverter.ToUInt64(uInt64Bytes, 0);
                payloadData = new byte[len];
                for (ulong i = 0; i < len; i++)
                {
                    payloadData[i] = bytes[i + 14];
                }
            }
            else
            {
                Array.Copy(bytes, 2, masks, 0, 4);
                payloadData = new byte[payloadLen];
                Array.Copy(bytes, 6, payloadData, 0, payloadLen);

            }

            for (var i = 0; i < payloadLen; i++)
            {
                payloadData[i] = (byte)(payloadData[i] ^ masks[i % 4]);
            }
            return Encoding.UTF8.GetString(payloadData);
        }

        /// <summary>
        /// 打包服务器数据
        /// </summary>
        /// <param name="message">数据</param>
        /// <returns></returns>
        private byte[] PackData(string message)
        {
            // http://blog.csdn.net/daonidedie/article/details/41963153
            var temp = CommunicationArgs.Encoding.GetBytes(message);
            byte[] contentBytes;
            if (temp.Length < 126)
            {
                contentBytes = new byte[temp.Length + 2];
                contentBytes[0] = 0x81;
                contentBytes[1] = (byte)temp.Length;
                Array.Copy(temp, 0, contentBytes, 2, temp.Length);
            }
            else if (temp.Length < 0xFFFF)
            {
                contentBytes = new byte[temp.Length + 4];
                contentBytes[0] = 0x81;
                contentBytes[1] = 126;
                //var ushortlen = BitConverter.GetBytes((ushort)temp.Length);
                contentBytes[2] = (byte)(temp.Length >> 8 & 0xFF); //ushortlen[1];
                contentBytes[3] = (byte)(temp.Length & 0xFF); //ushortlen[0];
                Array.Copy(temp, 0, contentBytes, 4, temp.Length);
            }
            else
            {
                contentBytes = new byte[temp.Length + 10];
                contentBytes[0] = 0x81;
                contentBytes[1] = 127;
                var ulonglen = BitConverter.GetBytes((ulong)temp.Length);
                contentBytes[2] = ulonglen[7];
                contentBytes[3] = ulonglen[6];
                contentBytes[4] = ulonglen[5];
                contentBytes[5] = ulonglen[4];
                contentBytes[6] = ulonglen[3];
                contentBytes[7] = ulonglen[2];
                contentBytes[8] = ulonglen[1];
                contentBytes[9] = ulonglen[0];
                Array.Copy(temp, 0, contentBytes, 10, temp.Length);
            }
            return contentBytes;
        }

        /// <summary>
        /// 打包服务器数据
        /// </summary>
        /// <param name="temp">数据</param>
        /// <returns></returns>
        private byte[] PackData(byte[] temp)
        {
            // http://blog.csdn.net/daonidedie/article/details/41963153
            // var temp = CommunicationArgs.Encoding.GetBytes(message);
            byte[] contentBytes;
            if (temp.Length < 126)
            {
                contentBytes = new byte[temp.Length + 2];
                contentBytes[0] = 0x81;
                contentBytes[1] = (byte)temp.Length;
                Array.Copy(temp, 0, contentBytes, 2, temp.Length);
            }
            else if (temp.Length < 0xFFFF)
            {
                contentBytes = new byte[temp.Length + 4];
                contentBytes[0] = 0x81;
                contentBytes[1] = 126;
                //var ushortlen = BitConverter.GetBytes((ushort)temp.Length);
                contentBytes[2] = (byte)(temp.Length >> 8 & 0xFF); //ushortlen[1];
                contentBytes[3] = (byte)(temp.Length & 0xFF); //ushortlen[0];
                Array.Copy(temp, 0, contentBytes, 4, temp.Length);
            }
            else
            {
                contentBytes = new byte[temp.Length + 10];
                contentBytes[0] = 0x81;
                contentBytes[1] = 127;
                var ulonglen = BitConverter.GetBytes((ulong)temp.Length);
                contentBytes[2] = ulonglen[7];
                contentBytes[3] = ulonglen[6];
                contentBytes[4] = ulonglen[5];
                contentBytes[5] = ulonglen[4];
                contentBytes[6] = ulonglen[3];
                contentBytes[7] = ulonglen[2];
                contentBytes[8] = ulonglen[1];
                contentBytes[9] = ulonglen[0];
                Array.Copy(temp, 0, contentBytes, 10, temp.Length);
            }
            return contentBytes;
        }

        /// <summary>
        /// 获取当前 Socket 使用的 IP
        /// </summary>
        /// <returns></returns>
        public string GetSocketLocalEndPoint()
        {
            return _socket.LocalEndPoint.ToString();
        }

        /// <summary>
        /// 获取当前 Socket 使用的 IP
        /// </summary>
        /// <returns></returns>
        public string GetSocketRemoteEndPoint()
        {
            return _socket.RemoteEndPoint.ToString();
        }

        /// <summary>
        /// 初始化 Udp 客户端
        /// </summary>
        /// <returns></returns>
        public bool InitializeUdpClient()
        {
            if (_communicationMode == CommunicationModes.UdpClient)
            {
                try
                {
                    _socket.Bind(CommunicationArgs.EndPoint);
                    _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
                    ThreadPool.QueueUserWorkItem(UdpReceived, _socket);
                }
                catch (Exception e)
                {
                    ErrorInfo = e.Message;
                    ErrorCode = CommunicationErrors.CommunicationError;
                    return false;
                }
                return true;
            }

            ErrorInfo = "当前通信对象不支持 Udp 通信。";
            ErrorCode = CommunicationErrors.ModeMismatching;
            return false;
        }

        /// <summary>
        /// 处理 Udp 消息
        /// </summary>
        /// <param name="obj"></param>
        private void UdpReceived(object obj)
        {
            var udpClient = (Socket)obj;
            var dictPackage = new Dictionary<string, List<UdpDataPackageInfo>>();
            while (true)
            {
                try
                {
                    EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
                    var bytes = new byte[UdpDataPackageInfo.SumLength + CommunicationArgs.UdpDataLength];
                    try
                    {
                        udpClient.ReceiveFrom(bytes, ref endPoint);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                        throw;
                    }
                    var id = CommunicationArgs.Encoding.GetString(bytes, 0, 32);
                    var count = Convert.ToInt32(Encoding.UTF8.GetString(bytes, 32, 10));
                    var index = Convert.ToInt32(Encoding.UTF8.GetString(bytes, 32 + 10, 10));
                    var size = Convert.ToInt32(Encoding.UTF8.GetString(bytes, 32 + 10 + 10, 10));
                    var endPointBySend = Encoding.UTF8.GetString(bytes, 32 + 10 + 10 + 10, 21).Trim(char.MinValue);
                    var toEndPointBySend = Encoding.UTF8.GetString(bytes, 32 + 10 + 10 + 10 + 21, 21).Trim(char.MinValue);
                    var receiveBytes = new byte[size];
                    Array.Copy(bytes, 32 + 10 + 10 + 10 + 21 + 21, receiveBytes, 0, size);

                    var info = UdpDataPackageInfo.GetDataPackageInfo(id, count, index, size, endPointBySend,
                        toEndPointBySend, CommunicationArgs.Encoding, endPoint.ToString(),
                        udpClient.LocalEndPoint.ToString(), receiveBytes);

                    if (index == count - 1)
                    {
                        if (dictPackage.ContainsKey(id))
                        {
                            dictPackage[id].Add(info);
                            if (UdpMessageReceived != null)
                            {
                                UdpMessageReceived.Invoke(this, new UdpMessageReceivedEventArgs(endPoint, id, dictPackage[id].ToArray()));
                            }
                            dictPackage.Remove(id);
                        }
                        else
                        {
                            if (UdpMessageReceived != null)
                            {
                                UdpMessageReceived.Invoke(this, new UdpMessageReceivedEventArgs(endPoint, id, info));
                            }
                        }
                        var ids = new List<string>();
                        foreach (var keyValuePair in dictPackage)
                        {
                            var last = keyValuePair.Value.OrderByDescending(n => n.ReceiveTime).First();
                            if (DateTime.Now - last.ReceiveTime > TimeSpan.FromMinutes(10))
                            {
                                ids.Add(keyValuePair.Key);
                            }
                        }
                        if (ids.Count != 0)
                        {
                            ids.ForEach(n => dictPackage.Remove(n));
                            GC.Collect();
                        }
                    }
                    else
                    {
                        if (dictPackage.ContainsKey(id))
                        {
                            dictPackage[id].Add(info);
                        }
                        else
                        {
                            dictPackage.Add(id, new List<UdpDataPackageInfo>());
                            dictPackage[id].Add(info);
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            }
        }

        /// <summary>
        /// 发送 Udp 消息
        /// </summary>
        /// <param name="endPoint">接收者网络地址</param>
        /// <param name="bytes">发送数据</param>
        public void SendUdpMessage(EndPoint endPoint, byte[] bytes)
        {
            var length = bytes.Length;
            var count = (int)Math.Ceiling((decimal)length / CommunicationArgs.UdpDataLength);
            var dataPackage = UdpDataPackageInfo.GetNewDataPackageInfo(count, CommunicationArgs.UdpDataLength,
                _socket.LocalEndPoint.ToString(), endPoint.ToString(), CommunicationArgs.Encoding);
            var sendLength = CommunicationArgs.UdpDataLength;
            for (var i = 0; i < count; i++)
            {
                dataPackage.Index = i;
                var sendBytes = new byte[UdpDataPackageInfo.SumLength + CommunicationArgs.UdpDataLength];
                Array.Copy(dataPackage.GetBytes(), sendBytes, UdpDataPackageInfo.SumLength);
                if (bytes.Length - i * CommunicationArgs.UdpDataLength < CommunicationArgs.UdpDataLength)
                {
                    sendLength = bytes.Length - i * CommunicationArgs.UdpDataLength;
                }
                Array.Copy(bytes, i * CommunicationArgs.UdpDataLength, sendBytes, UdpDataPackageInfo.SumLength,
                    sendLength);
                _socket.SendTo(sendBytes, endPoint);
            }
        }

        /// <summary>
        ///  收到 Udp 消息事件
        /// </summary>
        [Description("当收到 Udp 消息时发生")]
        public event EventHandler<UdpMessageReceivedEventArgs> UdpMessageReceived;
    }
}
